################################################################################
# IMPORTS
################################################################################

import random

from django.core.paginator import Paginator, InvalidPage, EmptyPage

from django.conf import settings

from django import template
from django.utils.translation import ugettext as _

from django.template.defaultfilters import stringfilter

################################################################################
# Utility functions
################################################################################
def get_children_weight(term):
    """
    return a list of all children of this term along with there weight.

    @term: the term to be used as parent.
    """
    data = term.get_render_data()
    res = []
    for child in data.children:
        if len(child.instances) > 0:
            res.append({'term':child.term, 'weight':len(child.instances)})
        if len(child.children) > 0:
            res += get_children_weight(child.term)
    return res

def taxonomy_sort_weight(wlist, min, max):
    """
    takes the output of get_children_weight and returns adjusted weight min to max

    @wlist: the list of terms and weights
    @min: minimum size
    @max: maximum size
    """
    tlist = [(item['weight'], item) for item in wlist]
    tlist.sort()
    inc = float(max - min) / (tlist[-1][0] - tlist[0][0])
    return [{'term':i[1]['term'],'weight':min+int(inc*i[1]['weight'])} for i in tlist]

################################################################################
# Register library
################################################################################

register = template.Library()

################################################################################
# TAG taxonomy_render_term
################################################################################

@register.inclusion_tag('taxonomy_render_term.html')
def taxonomy_render_term(term, page=1, num_items=10):
    """
    render a term

    @term: the term to render
    @page: the page number you want to render (if more then one page)
    @num_items: the maximum number of instances to display on a single page
    """
    data = term.get_render_data(1)
    paginator = Paginator(data['instances'], num_items)
    try:
        instance_list = paginator.page(page)
    except (EmptyPage, InvalidPage):
        instance_list = paginator.page(paginator.num_pages)
    data['paginator'] = instance_list
    return data

################################################################################
# TAG taxonomy_render_list
################################################################################

@register.inclusion_tag('taxonomy_render_list.html')
def taxonomy_render_list(term, active_term=None, depth=-1):
    """
    render a taxonomy list

    @term: the term to use as parent for the list
    @active_term: one of the child of term that is considered to be active
                  if not None, the match term will have the 'taxonomy-active'
                  css class added to it's list item.
    @depth: the depth to which to render the list.
    """
    data = term.get_render_data(depth)
    data['active_term'] = active_term
    return data

################################################################################
# TAG taxonomy_admin_render_list
################################################################################

@register.inclusion_tag('taxonomy_admin_render_list.html')
def taxonomy_admin_render_list(term, indent):
    """ render a taxonomy list for the django admin """
    data = term.get_render_data(2)
    data['indent'] = indent + 1
    data['max_reached'] = (indent >= 5)
    return data

################################################################################
# TAG taxonomy_render_cloud
################################################################################
@register.inclusion_tag('taxonomy_render_cloud.html')
def taxonomy_render_cloud(term, min_size=80, max_size=120):
    """
    render a taxonomy cloud

    The taxonomy cloud, as you would expect, is just a series of link to
    term with different font size related to the number of instances in relation
    to the term.

    @term: all child of this term will be displayed in the cloud
    @min_size: the minimum font size in the cloud
    @max_size: the maximum font size in the cloud
    """
    cloud = taxonomy_sort_weight(get_children_weight(term), min_size, max_size)
    random.shuffle(cloud)
    return {'cloud':cloud}

################################################################################
# TAG taxonomy_render_tower
################################################################################
@register.inclusion_tag('taxonomy_render_tower.html')
def taxonomy_render_tower(term, min_size=80, max_size=120):
    """
    render a taxonomy tower

    Same as above but in the form of a list order by reverse instance counts

    @term: all child of this term will be displayed in the tower
    @min_size: the minimum font size in the tower
    @max_size: the maximum font size in the tower
    """
    tower = taxonomy_sort_weight(get_children_weight(term), min_size, max_size)
    tower.reverse()
    return {'tower':tower}

